﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Omi.Xna.Collada.Model;
using Omi.Xna.Collada.Model.Animation;

namespace ColladaViewer
{
    public partial class AnimationPanel : UserControl
    {
        private IModel model;
        private ModelViewControl modelView;

        private Timer playbackTimer;

        private bool playing = false;
        private float fps = 30;
        private float advancedTime = 0;

        public AnimationPanel()
        {
            InitializeComponent();
            Enabled = false;

            playbackTimer = new Timer();
            playbackTimer.Tick += playbackTimer_Tick;
            playbackTimer.Interval = (int)Math.Round(1000.0f / fps);
            playbackTimer.Enabled = false;                        
        }

        private void playbackTimer_Tick(object sender, EventArgs e)
        {            
            if (model is SoftwareSkinnedModel)
            {
                var skinnedModel = model as SoftwareSkinnedModel;

                float advance = playbackTimer.Interval *
                                (speedTrack.Value / 100.0f) / 1000.0f;
                advancedTime += advance;

                int animIndex = animationListBox.SelectedIndex;
                var animation = skinnedModel.Data.JointAnimations[animIndex];

                skinnedModel.PlayAnimation(animation, advance);

                modelView.Invalidate();

                float duration = animation.Channels.Max(c => c.Sampler.EndTime);
                int trackBarProgress = (int)((advancedTime) * 100);
                playTrack.Value = trackBarProgress % playTrack.Maximum;                                
            }
        }

        void SetAnimationTime(float absoluteTime)
        {
            if (model is SoftwareSkinnedModel)
            {
                var skinnedModel = model as SoftwareSkinnedModel;               
                int animIndex = animationListBox.SelectedIndex;
                var animation = skinnedModel.Data.JointAnimations[animIndex];
                float duration = animation.Channels.Max(c => c.Sampler.EndTime);

                advancedTime = absoluteTime;
                if (advancedTime < 0) advancedTime = 0;
                else if (advancedTime >= duration) advancedTime = 0;

                skinnedModel.SetAnimationTime(animation, advancedTime);

                modelView.Invalidate();
                
                int trackBarProgress = (int)((advancedTime) * 100);
                playTrack.Value = trackBarProgress % playTrack.Maximum;
            }
        }

        public void Init(IModel model, ModelViewControl modelView)
        {            
            if (model == null || !model.Data.JointAnimations.Any())
            {
                animationListBox.Items.Clear();
                Enabled = false;
                return;
            }

            this.model = model;
            this.modelView = modelView;
            Enabled = true;

            // List animations
            animationListBox.Items.Clear();

            foreach (var anim in model.Data.JointAnimations)
            {
                string name = anim.Name;
                if (String.IsNullOrEmpty(name))
                    name = "(unnamed)";

                animationListBox.Items.Add(name);                
            }

            animationListBox.SelectedIndex = 0;
            animationListBox.SelectionMode = SelectionMode.One;

            InitPlayer();
        }

        void InitPlayer()
        {
            int animIndex = animationListBox.SelectedIndex;
            JointAnimation animation = model.Data.JointAnimations[animIndex];

            playTrack.Maximum = (int)(animation.Channels.Max(c => c.Sampler.EndTime) * 100);
            playTrack.Minimum = 0;
            playTrack.TickFrequency = 10;
            playTrack.Value = 0;
            playTrack.Invalidate();

            speedTrack.Value = 100;

            playButton.Text = "Play";
        }

        private void playButton_Click(object sender, EventArgs e)
        {
            if (!playing)
            {
                playing = true;
                playButton.Text = "Stop";

                advancedTime = 0;

                playbackTimer.Enabled = true;
                playbackTimer.Start();
            }
            else
            {
                playing = false;
                playButton.Text = "Play";

                playbackTimer.Enabled = false;
                playbackTimer.Stop();
            }
        }

        private void playTrack_ValueChanged(object sender, EventArgs e)
        {
            if (Math.Abs(playTrack.Value - advancedTime * 100) > 3)
            {
                float time = (float) playTrack.Value / 100.0f;                
                SetAnimationTime(time);
            }
        }

        private void playTrack_MouseUp(object sender, MouseEventArgs e)
        {
            
        }
    }
}
